import heuristicFunctions.ManhattanDistance;

import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import aima.core.agent.Action;
import aima.core.search.framework.GraphSearch;
import aima.core.search.framework.Problem;
import aima.core.search.framework.Search;
import aima.core.search.framework.SearchAgent;
import aima.core.search.framework.StepCostFunction;
import aima.core.search.framework.TreeSearch;
import aima.core.search.informed.AStarSearch;
import aima.core.search.uninformed.BreadthFirstSearch;
import aima.core.search.uninformed.DepthFirstSearch;
import aima.core.search.uninformed.IterativeDeepeningSearch;
import domain.PacmanActionsFunction;
import domain.PacmanBoard;
import domain.PacmanGoalTest;
import domain.PacmanResultFunction;
import domain.SearchType;
import entry.runRandomized;

public class Application {

	private static final String FILE_PATH = "files\\kruimelMedium.txt";

	public static void main(String[] args) {
			
		
		// RANDOM MODE
		runRandomized randomizedRun = new runRandomized();
		randomizedRun.runTests();
		
		
	
		/* MANUAL MODE (in commentaar gezet om random generatie te runnen)
		char[][] map = TextFileReader.getMap(FILE_PATH);

		PacmanBoard board = new PacmanBoard(map);

		System.out.println("Before search:");
		board.printBoard();

		Problem problem = createProblem(board, new EStepCostFunction());
		Search search = createSearch(SearchType.AStar);
		performSearch(problem, search);
		*/
		
	}
	
	public static Problem createProblem(PacmanBoard pacmanBoard) {
		return new Problem(pacmanBoard, new PacmanActionsFunction(), new PacmanResultFunction(), new PacmanGoalTest());		
	}
	
	public static Problem createProblem(PacmanBoard pacmanBoard, StepCostFunction stepCostFunction) {
		return new Problem(pacmanBoard, new PacmanActionsFunction(), new PacmanResultFunction(), new PacmanGoalTest(), stepCostFunction);		
	}
	
	public static Search createSearch(SearchType search) {
		switch(search) {
			case BFSTree: return new BreadthFirstSearch(new TreeSearch());
			case BFSGraph: return new BreadthFirstSearch(new GraphSearch());
			case DFS: return new DepthFirstSearch(new GraphSearch());
			case ID: return new IterativeDeepeningSearch();
			case AStar: return new AStarSearch(new GraphSearch(), new ManhattanDistance());
		}
		return null;
	}
	
	public static Properties performSearch(Problem problem, Search search) {
		SearchAgent agent;		
		try {
			
			agent = new SearchAgent(problem, search);
			printActions(agent.getActions());
			printInstrumentation(agent.getInstrumentation());
			return agent.getInstrumentation();
			
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}	
	}
	
	private static void printInstrumentation(Properties properties) {
		System.out.println("\nPrinting instrumentation: ");
		Iterator<Object> keys = properties.keySet().iterator();
		while (keys.hasNext()) {
			String key = (String) keys.next();
			String property = properties.getProperty(key);
			System.out.println(key + " : " + property);
		}

	}

	private static void printActions(List<Action> actions) {
		System.out.println("\nPrinting actions: ");
		for (int i = 0; i < actions.size(); i++) {
			String action = actions.get(i).toString();
			System.out.print(action + "\t");
			if((i+1)%10 == 0)
				System.out.print("\n");			
		}
	}

}